package com.easylive.service.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

import javax.annotation.Resource;

import com.easylive.entity.component.RedisComponent;
import com.easylive.entity.constants.Constants;
import com.easylive.entity.po.VideoInfo;
import com.easylive.entity.query.VideoInfoQuery;
import com.easylive.exception.BusinessException;
import com.easylive.mappers.VideoInfoMapper;
import org.springframework.stereotype.Service;

import com.easylive.entity.enums.PageSize;
import com.easylive.entity.query.CategoryInfoQuery;
import com.easylive.entity.po.CategoryInfo;
import com.easylive.entity.vo.PaginationResultVO;
import com.easylive.entity.query.SimplePage;
import com.easylive.mappers.CategoryInfoMapper;
import com.easylive.service.CategoryInfoService;
import com.easylive.utils.StringTools;
import org.springframework.util.ObjectUtils;


/**
 *  业务接口实现
 */
@Service("categoryInfoService")
public class CategoryInfoServiceImpl implements CategoryInfoService {

	@Resource
	private CategoryInfoMapper<CategoryInfo, CategoryInfoQuery> categoryInfoMapper;

	@Resource
	private RedisComponent redisComponent;

	@Resource
	private VideoInfoMapper<VideoInfo, VideoInfoQuery> videoInfoMapper;

	/**
	 * 根据条件查询列表
	 */
	@Override
	public List<CategoryInfo> findListByParam(CategoryInfoQuery param) {
		List<CategoryInfo> list = this.categoryInfoMapper.selectList(param);
		if (param.getConvert2Tree() != null && param.getConvert2Tree()) {
			list = convertLine2Tree(list, Constants.ZERO);
		}
		return list;
	}

	/**
	 * 将线性结构转换为树形结构，需要在CategoryInfo中提供children属性
	 * @param dataList
	 * @param pid  0表示根节点
	 * @return
	 */
	private List<CategoryInfo> convertLine2Tree(List<CategoryInfo> dataList, Integer pid) {
		List<CategoryInfo> result = new ArrayList<>();
		/**
		 * 遍历所有节点
		 */
		for (CategoryInfo m : dataList) {
			/**
			 * 如果当前节点的父级ID等于传入的父级ID，则说明是它的子节点
			 */
			if (m.getCategoryId() != null && m.getpCategoryId() != null && m.getpCategoryId().equals(pid)) {
				/**
				 * 递归查找子节点
				 */
				m.setChildren(convertLine2Tree(dataList, m.getCategoryId()));
				result.add(m);
			}
		}
		return result;
	}

	/**
	 * 根据条件查询列表
	 */
	@Override
	public Integer findCountByParam(CategoryInfoQuery param) {
		return this.categoryInfoMapper.selectCount(param);
	}

	/**
	 * 分页查询方法
	 */
	@Override
	public PaginationResultVO<CategoryInfo> findListByPage(CategoryInfoQuery param) {
		int count = this.findCountByParam(param);
		int pageSize = param.getPageSize() == null ? PageSize.SIZE15.getSize() : param.getPageSize();

		SimplePage page = new SimplePage(param.getPageNo(), count, pageSize);
		param.setSimplePage(page);
		List<CategoryInfo> list = this.findListByParam(param);
		PaginationResultVO<CategoryInfo> result = new PaginationResultVO(count, page.getPageSize(), page.getPageNo(), page.getPageTotal(), list);
		return result;
	}

	/**
	 * 新增
	 */
	@Override
	public Integer add(CategoryInfo bean) {
		return this.categoryInfoMapper.insert(bean);
	}

	/**
	 * 批量新增
	 */
	@Override
	public Integer addBatch(List<CategoryInfo> listBean) {
		if (listBean == null || listBean.isEmpty()) {
			return 0;
		}
		return this.categoryInfoMapper.insertBatch(listBean);
	}

	/**
	 * 批量新增或者修改
	 */
	@Override
	public Integer addOrUpdateBatch(List<CategoryInfo> listBean) {
		if (listBean == null || listBean.isEmpty()) {
			return 0;
		}
		return this.categoryInfoMapper.insertOrUpdateBatch(listBean);
	}

	/**
	 * 多条件更新
	 */
	@Override
	public Integer updateByParam(CategoryInfo bean, CategoryInfoQuery param) {
		StringTools.checkParam(param);
		return this.categoryInfoMapper.updateByParam(bean, param);
	}

	/**
	 * 多条件删除
	 */
	@Override
	public Integer deleteByParam(CategoryInfoQuery param) {
		StringTools.checkParam(param);
		return this.categoryInfoMapper.deleteByParam(param);
	}

	/**
	 * 根据CategoryId获取对象
	 */
	@Override
	public CategoryInfo getCategoryInfoByCategoryId(Integer categoryId) {
		return this.categoryInfoMapper.selectByCategoryId(categoryId);
	}

	/**
	 * 根据CategoryId修改
	 */
	@Override
	public Integer updateCategoryInfoByCategoryId(CategoryInfo bean, Integer categoryId) {
		return this.categoryInfoMapper.updateByCategoryId(bean, categoryId);
	}

	/**
	 * 根据CategoryId删除
	 */
	@Override
	public Integer deleteCategoryInfoByCategoryId(Integer categoryId) {
		return this.categoryInfoMapper.deleteByCategoryId(categoryId);
	}

	/**
	 * 根据CategoryCode获取对象
	 */
	@Override
	public CategoryInfo getCategoryInfoByCategoryCode(String categoryCode) {
		return this.categoryInfoMapper.selectByCategoryCode(categoryCode);
	}

	/**
	 * 根据CategoryCode修改
	 */
	@Override
	public Integer updateCategoryInfoByCategoryCode(CategoryInfo bean, String categoryCode) {
		return this.categoryInfoMapper.updateByCategoryCode(bean, categoryCode);
	}

	/**
	 * 根据CategoryCode删除
	 */
	@Override
	public Integer deleteCategoryInfoByCategoryCode(String categoryCode) {
		return this.categoryInfoMapper.deleteByCategoryCode(categoryCode);
	}

	@Override
	public void saveCategory(CategoryInfo bean) {
		CategoryInfo dbBean = categoryInfoMapper.selectByCategoryCode(bean.getCategoryCode());
		/**
		 * 新增时：编码已经存在，抛出异常
		 * 修改时：编码已经存在，并且id不一致，说明改的编码和库里的重复了，抛出异常
		 */
		if (bean.getCategoryId() == null && dbBean != null
			|| bean.getCategoryId() != null && dbBean != null && !Objects.equals(bean.getCategoryId(), dbBean.getCategoryId())
		) {
			throw new BusinessException("分类编码已存在");
		}

		if (bean.getCategoryId() == null) {
			// 新增

			/**
			 * 设置排序码，页面上没有显示设置，从数据库里面取出最大的排序吗然后+1
			 * 传入父级分类ID，因为没有子分类，父级ID为0，就需要从0中取出最大的排序码
			 * 如果有父级ID，就从父级ID中取出最大的排序码
			 */
			Integer maxSort = categoryInfoMapper.selectMaxSort(bean.getpCategoryId());
			bean.setSort(maxSort + 1);
			categoryInfoMapper.insert(bean);
		} else {
			// 修改
			categoryInfoMapper.updateByCategoryId(bean, bean.getCategoryId());
		}
		save2Redis();
	}

	@Override
	public void delCategory(Integer categoryId) {
		// 查询分类下是否有视频，有则不能删除
		VideoInfoQuery videoInfoQuery = new VideoInfoQuery();
		videoInfoQuery.setpCategoryId(categoryId);
		Integer count = videoInfoMapper.selectCount(videoInfoQuery);
		if (count > 0) {
			throw new BusinessException("当前分类下有视频，不能删除");
		}
		/**
		 * 删除父分类时，子分类也要删除，需要修改xml Mybatis语句
		 */
		CategoryInfoQuery query = new CategoryInfoQuery();
		query.setCategoryIdOrPCategoryId(categoryId);
		categoryInfoMapper.deleteByParam(query);

		/**
		 * 分类查出来放缓存中，系统中很多地方需要用，并且不是经常修改，不需要每次都查数据库
		 */
		save2Redis();

	}

	/**
	 * 修改分类排序
	 * @param pCategoryId 0 或者 其他父分类ID
	 * @param categoryIds
	 */
	@Override
	public void changeSort(Integer pCategoryId, String categoryIds) {
		/**
		 * 前端已经做了排序，这里只需要修改排序码即可
		 */
		String[] categoryIdArray = categoryIds.split(",");
		List<CategoryInfo> categoryInfoList = new ArrayList<>();

		Integer sort = 0;
		for (String categoryId : categoryIdArray) {
			CategoryInfo categoryInfo = new CategoryInfo();
			categoryInfo.setpCategoryId(pCategoryId);
			categoryInfo.setCategoryId(Integer.valueOf(categoryId));
			/**
			 * 重新排序即可，排序码从1开始，需要用++i
			 */
			categoryInfo.setSort(++sort);
			categoryInfoList.add(categoryInfo);
		}

		categoryInfoMapper.updateSortBatch(categoryInfoList);

		save2Redis();

	}

	@Override
	public List<CategoryInfo> getAllCategoryList() {
		List<CategoryInfo> categoryInfo = redisComponent.getCategoryInfo();
		// 如果缓存中没有数据，则从数据库中查询并保存到缓存中
		if (categoryInfo.isEmpty()) {
			save2Redis();
		}
		return categoryInfo;
	}

	private void save2Redis() {
		CategoryInfoQuery query = new CategoryInfoQuery();
		query.setOrderBy("sort asc");
		query.setConvert2Tree(true);
		List<CategoryInfo> list = findListByParam(query);
		redisComponent.saveCategoryInfo(list);
	}
}